home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / win / c / winet.com / SYMFILE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1987-05-12  |  5.0 KB  |  215 lines

  1. /*
  2.  * This file contains procedures to process a symbol file.
  3.  * 
  4.  * The following operations are required:
  5.  * 
  6.  *     Open a symbol file.
  7.  *     Scan through the segments in a symbol file.
  8.  *     For a given segment scan through the symbols.
  9.  *     For each symbol, store the symbol value in an array.
  10.  */
  11. #include <stdio.h>
  12. #include <process.h>
  13. #include <string.h>
  14. #include <malloc.h>
  15. #include <dgb.h>
  16. #include <exc.h>
  17. #include "types.h"
  18. #include "symfile.h"
  19. #include "segments.h"
  20. #include "profile.h"
  21.  
  22. SYMHDR SFheader;
  23. SYMSEG SFseg;
  24. PNSTR ModuleName = NULL;
  25.  
  26. PSTR FileName;
  27. FILE *CurrentSymbolFile = NULL;
  28. WORD LastPara = 0;
  29.  
  30. void CloseSymbolFile()
  31. {
  32.    if (CurrentSymbolFile != NULL)
  33.    {
  34.       fclose (CurrentSymbolFile);
  35.       CurrentSymbolFile = NULL;
  36.       if (ModuleName != NULL)
  37.       {
  38.      free((char *)ModuleName);
  39.      ModuleName = NULL;
  40.       }
  41.       FileName = NULL;
  42.    }
  43. }
  44.  
  45. /*
  46.  * Open a symbol file. Path searching has already been done.
  47.  */
  48. FILE *OpenSymFile (name)
  49. PSTR name;
  50. {
  51.    if (CurrentSymbolFile != NULL) CloseSymbolFile();
  52.    FileName = name;
  53.    CurrentSymbolFile = fopen(name, "rb");
  54.    if (CurrentSymbolFile == NULL)
  55.    {
  56.       BadFile = name; exc_raise(OP_FAILED);
  57.    }
  58.    fread ((char *)&SFheader, sizeof(SYMHDR), 1, CurrentSymbolFile);
  59.    ModuleName = ReadName();
  60.    return CurrentSymbolFile;
  61. }
  62.  
  63. BOOL IsSymFileName(name)
  64. PSTR name;
  65. {
  66.    WORD l = strlen(name);
  67.    if (l > 4 && strcmpi(name+l-4, ".SYM") == 0) return TRUE;
  68.    return FALSE;
  69. }
  70.  
  71. WORD RdWord ()
  72. {
  73.    WORD w;
  74.    fread ((char *)&w, 2, 1, CurrentSymbolFile);
  75.    return w;
  76. }
  77.  
  78. void LoadSymFile (name)
  79. PSTR name;
  80. {
  81.    WORD seg;
  82.    WORD i;
  83.    OpenSymFile (name);
  84.    fprintf(stderr, "Reading '%s'... %d segment%s\n", name, SFheader.Nsegs, (SFheader.Nsegs == 1?"":"s"));
  85.    seg = SFheader.FirstSeg;
  86.    for (i = 0; i < SFheader.Nsegs; i++)
  87.    {
  88.       seg = LoadSegment (seg);
  89.    }
  90.    CloseSymbolFile();
  91. }
  92.  
  93. PNSTR ReadName()
  94. {
  95.    BYTE l = (BYTE) getc (CurrentSymbolFile);
  96.    PNSTR n = (PNSTR) emalloc (sizeof(NSTR) + l);
  97.    n->len = l;
  98.    fread (n->s, l, 1, CurrentSymbolFile);
  99.    n->s[l] = 0;
  100.    return n;
  101. }
  102.  
  103. void SkipName()
  104. {
  105.    BYTE l = (BYTE) getc (CurrentSymbolFile);
  106.    fseek (CurrentSymbolFile, (long) l, SEEK_CUR);
  107. }
  108.  
  109.  
  110. WORD LoadSegment(offset)
  111. WORD offset;
  112. {
  113.    PNSTR SegName;
  114.    PPD ProcDesc;
  115.    WORD vsize;
  116.    WORD i;
  117.    PSEGMENT ps;
  118.    fseek (CurrentSymbolFile, offset * 16L, SEEK_SET);
  119.    fread ((char *) &SFseg, sizeof(SYMSEG), 1, CurrentSymbolFile);
  120.    SegName = ReadName();
  121.    fprintf(stderr, "Segment %s!%s %d symbol%s\n", ModuleName->s, SegName->s, SFseg.Nsyms, (SFseg.Nsyms==1?"":"s"));
  122.    vsize = sizeof (VALBLOCK) * (SFseg.Nsyms-1) + sizeof(PD);
  123.  
  124.    ProcDesc = (PPD) emalloc (vsize);
  125.  
  126.    ProcDesc->filename = FileName;
  127.    ProcDesc->segname = SegName;
  128.    ProcDesc->len = SFseg.Nsyms;
  129.    for (i = 0; i < SFseg.Nsyms; i++)
  130.    {
  131.       ProcDesc->vals[i].label = RdWord();
  132.       ProcDesc->vals[i].count = 0;
  133.       SkipName();
  134.    }
  135.    /* Now install this segment in my list... */
  136.    ps = (PSEGMENT) DefineSegment ((LPSTR) ModuleName->s, SFseg.Ordinal-1, 0, 0, 0);
  137.    if (ps != NULL) ps->Procs = ProcDesc;
  138.    return SFseg.ParaNext;
  139. }
  140.  
  141. /*
  142.  * This code is used for output to translate the addresses into symbols.
  143.  * To keep it simple, it only runs well if it is called for increasing addresses.
  144.  * This should be the normal case.
  145.  */
  146. WORD OldOrdinal = 0;
  147. WORD OldOffset = 0;
  148. WORD SymsLeft = 0;
  149.  
  150. static PNSTR SearchForSymbol (WORD);
  151. static BOOL SearchForSegment (WORD);
  152. static WORD LoadSegHdr (WORD);
  153.  
  154. PNSTR FindSymbol (file, SegOrdinal, Offset)
  155. PSTR file;
  156. WORD SegOrdinal;
  157. WORD Offset;
  158. {
  159.    /*printf("Looking in %s for %04x:%04x\n", file, SegOrdinal, Offset);*/
  160.    if (file == FileName && SegOrdinal == OldOrdinal && Offset > OldOffset)
  161.       return SearchForSymbol (Offset);
  162.  
  163.    OldOrdinal = SegOrdinal;
  164.    OldOffset = Offset;
  165.    if (file != FileName) OpenSymFile (file);
  166.    unless (SearchForSegment (SegOrdinal)) return NULL;
  167.    SearchForSymbol (Offset);
  168. }
  169.  
  170. /* Opened correct file, found the right segment. Now just search for the symbol. */
  171. static PNSTR SearchForSymbol (Offset)
  172. WORD Offset;
  173. {
  174.    while (SymsLeft > 0)
  175.    {
  176.       WORD label = RdWord();
  177.       /*printf(" %04x", label);*/
  178.       if (label == Offset)
  179.       {
  180.      return ReadName();
  181.       }
  182.       SkipName();
  183.       SymsLeft--;
  184.       if (label > Offset) return NULL;
  185.    }
  186.    return NULL;
  187. }
  188.  
  189. static BOOL SearchForSegment (SegOrd)
  190. WORD SegOrd;
  191. {
  192.    WORD seg = SFheader.FirstSeg;
  193.    WORD i;
  194.    for (i = 0; i < SFheader.Nsegs; i++)
  195.    {
  196.       seg = LoadSegHdr (seg);
  197.       /*printf("Looking at segment %d\n", SFseg.Ordinal);*/
  198.       if (SFseg.Ordinal == SegOrd)
  199.       {
  200.      SymsLeft = SFseg.Nsyms;
  201.      return TRUE;
  202.       }
  203.    }
  204.    return FALSE;
  205. }
  206.  
  207. static WORD LoadSegHdr (offset)
  208. WORD offset;
  209. {
  210.    fseek (CurrentSymbolFile, offset * 16L, SEEK_SET);
  211.    fread ((char *) &SFseg, sizeof(SYMSEG), 1, CurrentSymbolFile);
  212.    SkipName(); /* Dont want segment name this time */
  213.    return SFseg.ParaNext;
  214. }
  215.